home *** CD-ROM | disk | FTP | other *** search
/ Programming Sound Cards / Programming Sound Cards.iso / sound_87 / loader66.pas < prev    next >
Pascal/Delphi Source File  |  1995-01-01  |  8KB  |  333 lines

  1. UNIT Loader669;
  2.  
  3. INTERFACE
  4.  
  5. USES Objects, SongUnit;
  6.  
  7.  
  8.  
  9.  
  10. PROCEDURE Load669FileFormat  (VAR Song: TSong; VAR St: TStream; VAR Header: TSongHeader);
  11.  
  12.  
  13.  
  14.  
  15. IMPLEMENTATION
  16.  
  17. USES SongElements, SongUtils, Heaps, AsciiZ;
  18.  
  19.  
  20.  
  21.  
  22. {----------------------------------------------------------------------------}
  23. { Internal definitions. Format of the files.                                 }
  24. {____________________________________________________________________________}
  25.  
  26. TYPE
  27.   T669FileMagic = WORD;
  28.  
  29. CONST
  30.   Magic669 = $6669;
  31.  
  32. TYPE
  33.  
  34.   TSizes = ARRAY[1..128] OF BYTE;
  35.  
  36.   T669Header =
  37.     RECORD
  38.       Magic       : T669FileMagic;
  39.       Comment     : ARRAY[1..3, 1..36] OF CHAR;
  40.       NInstruments: BYTE;
  41.       NPatterns   : BYTE;
  42.       RepStart    : BYTE;
  43.       Sequence    : ARRAY[1..128] OF BYTE;
  44.       Tempos      : ARRAY[1..128] OF BYTE;
  45.       Lengths     : TSizes;
  46.     END;
  47.  
  48.   T669Instrument =
  49.     RECORD
  50.       Name      : ARRAY[1..13] OF CHAR;
  51.       Size      : LONGINT;
  52.       RepStart  : LONGINT;
  53.       RepLen    : LONGINT;
  54.     END;
  55.  
  56.   T669Pattern = ARRAY[1..64, 1..8] OF
  57.     RECORD
  58.       CASE BYTE OF
  59.         0 : ( w1 : WORD;
  60.               b  : BYTE );
  61.         1 : ( b1,
  62.               b2,
  63.               b3 : BYTE );
  64.     END;
  65.  
  66.  
  67.  
  68.  
  69. PROCEDURE ProcessPatterns(VAR Song: TSong; VAR St: TStream; VAR Sizes: TSizes; Num: WORD);
  70.   VAR
  71.     Patt      : T669Pattern;
  72.     FullTrack : TFullTrack;
  73.     Pattern   : PPattern;
  74.     Track     : PTrack;
  75.     Note      : TFullNote;
  76.     c         : BYTE;
  77.     i, j      : WORD;
  78.     n, t      : WORD;
  79.     Row       : WORD;
  80.     Size      : WORD;
  81.     NAdj      : WORD;
  82.     l         : LONGINT;
  83.   BEGIN
  84.     t := 1;
  85.     FOR n := 1 TO Num DO
  86.       BEGIN
  87.         Pattern := Song.GetPattern(n);
  88.         IF Pattern = NIL THEN
  89.           BEGIN
  90.             Song.Status := msOutOfMemory;
  91.             EXIT;
  92.           END;
  93.  
  94.         WITH Pattern^.Patt^ DO
  95.           BEGIN
  96.             NNotes := Sizes[n] + 1;
  97.             NChans := Song.NumChannels;
  98.             Tempo  := 0;
  99.             BPM    := 0;
  100.           END;
  101.  
  102.         St.Read(Patt, SizeOf(Patt));
  103.  
  104.         IF St.Status <> stOk THEN
  105.           BEGIN
  106.             Song.Status := msFileTooShort;
  107.             EXIT;
  108.           END;
  109.  
  110.         FOR j := 1 TO Song.NumChannels DO
  111.           BEGIN
  112.             FillChar(FullTrack, SizeOf(FullTrack), 0);
  113.  
  114.             FOR i := 1 TO 64 DO
  115.               WITH FullTrack[i-1], Patt[i][j] DO
  116.                 BEGIN
  117.                   IF b1 < $FE THEN
  118.                     BEGIN
  119.                       Period     := PeriodArray[b1 SHR 2];
  120.                       Instrument := ((SWAP(w1) SHR 4) AND 63) + 1;
  121.                     END;
  122.  
  123.                   IF b1 < $FF THEN
  124.                     Volume   := ((b2 AND 15) SHL 2) + ((b2 AND 15) SHR 2) + 1;
  125.  
  126.                   Parameter  := b3 AND 15;
  127.                   Command    := mcNone;
  128.  
  129.                   IF Parameter <> 0 THEN
  130.                     CASE b3 SHR 4 OF
  131.                       0 : Command := mcTPortUp;
  132.                       1 : Command := mcTPortDown;
  133.                       2 : Command := mcNPortamento;
  134.                       3 : INC(Period);
  135.                       4 : BEGIN
  136.                             Command   := mcVibrato;
  137.                             Parameter := (Parameter SHL 4) + 1
  138.                           END;
  139.                       5 : Command := mcSetTempo;
  140.                     END;
  141.                 END;
  142.  
  143.             Track := Song.GetTrack(t);
  144.             IF Track = NIL THEN
  145.               BEGIN
  146.                 Song.Status := msOutOfMemory;
  147.                 EXIT;
  148.               END;
  149.  
  150.             Track^.SetFullTrack(FullTrack);
  151.  
  152.             Pattern^.Patt^.Channels[j] := t;
  153.  
  154.             INC(t);
  155.           END;
  156.  
  157.       END;
  158.   END;
  159.  
  160.  
  161. PROCEDURE ProcessInstruments(VAR Song: TSong; VAR St: TStream; Num: WORD);
  162.   VAR
  163.     Instrument : TInstrumentRec;
  164.     Instr      : PInstrument;
  165.     Instr669   : T669Instrument;
  166.     i, w       : WORD;
  167.     Signo      : LONGINT;
  168.     NoSigno    : LONGINT;
  169.   BEGIN
  170.     FOR i := 1 TO Num DO
  171.       WITH Instrument DO
  172.         BEGIN
  173.           FillChar(Instrument, SizeOf(Instrument), 0);
  174.  
  175.           Instr := Song.GetInstrument(i);
  176.           IF Instr = NIL THEN
  177.             BEGIN
  178.               Song.Status := msOutOfMemory;
  179.               EXIT;
  180.             END;
  181.  
  182.           St.Read(Instr669, SizeOf(Instr669));
  183.  
  184.           Instr^.SetName(StrASCIIZ(Instr669.Name, 13));
  185.  
  186.           Len  := Instr669.Size;
  187.  
  188.           IF Len > 0 THEN
  189.             BEGIN
  190.  
  191.               IF Instr669.RepLen <= Len THEN
  192.                 BEGIN
  193.                   Reps := Instr669.RepStart;
  194.                   Repl := Instr669.RepLen;
  195.                 END
  196.               ELSE
  197.                 BEGIN
  198.                   Reps := 0;
  199.                   Repl := 0;
  200.                 END;
  201.  
  202.               Vol  := 64;
  203.  
  204.               IF Repl        > Len THEN Repl := Len;
  205.               IF Reps + Repl > Len THEN Repl := Len - Reps;
  206.  
  207.  
  208.               Instr^.Change(@Instrument);
  209.             END
  210.           ELSE
  211.             Instr^.Change(NIL);
  212.         END;
  213.   END;
  214.  
  215.  
  216.  
  217. PROCEDURE ProcessSamples(VAR Song: TSong; VAR St: TStream; Num: WORD);
  218.   VAR
  219.     Instr      : PInstrument;
  220.     i, w       : WORD;
  221.   BEGIN
  222.     FOR i := 1 TO Num DO
  223.       BEGIN
  224.         Instr := Song.GetInstrument(i);
  225.  
  226.         IF (Instr^.Instr     <> NIL) AND
  227.            (Instr^.Instr^.Len > 0)   THEN
  228.           WITH Instr^.Instr^ DO
  229.             BEGIN
  230.               IF Len <= MaxSample THEN
  231.                 BEGIN
  232.                   FullHeap.HGetMem(POINTER(Data), Len);
  233.                   IF Data = NIL THEN BEGIN
  234.                     Song.Status := msOutOfMemory;
  235.                     EXIT;
  236.                   END;
  237.  
  238.                   St.Read(Data^, Len);
  239.  
  240.                   IF St.Status <> stOk THEN BEGIN
  241.                     Song.Status := msFileDamaged;
  242.                     EXIT;
  243.                   END;
  244.  
  245.                   FOR w := 0 TO Len - 1 DO
  246.                     INC(Data^[w], 128);
  247.  
  248.                 END
  249.               ELSE
  250.                 BEGIN
  251.                   FullHeap.HGetMem(POINTER(Data), MaxSample);
  252.                   FullHeap.HGetMem(POINTER(Xtra), Len-MaxSample);
  253.  
  254.                   IF (Data = NIL) OR (Xtra = NIL) THEN BEGIN
  255.                     Song.Status := msOutOfMemory;
  256.                     EXIT;
  257.                   END;
  258.  
  259.                   St.Read(Data^, MaxSample);
  260.                   St.Read(Xtra^, Len-MaxSample);
  261.  
  262.                   IF St.Status <> 0 THEN BEGIN
  263.                     Song.Status := msFileDamaged;
  264.                     EXIT;
  265.                   END;
  266.                 END;
  267.             END;
  268.       END;
  269.   END;
  270.  
  271. PROCEDURE Load669FileFormat(VAR Song: TSong; VAR St: TStream; VAR Header: TSongHeader);
  272.   VAR
  273.     Hdr        : T669Header ABSOLUTE Header;
  274.     InitialPos : LONGINT;
  275.     i          : WORD;
  276.   BEGIN
  277.     Song.FileFormat := mffComposer669;
  278.  
  279.     InitialPos := St.GetPos;
  280.  
  281.     St.Seek(InitialPos + SizeOf(T669Header));
  282.  
  283.     IF Hdr.Magic <> Magic669 THEN
  284.       BEGIN
  285.         Song.Status := msNotLoaded;
  286.         EXIT;
  287.       END;
  288.  
  289.     Song.Status := msOK;
  290.  
  291.     Song.Name := FullHeap.HNewStr(Song.FileName);
  292.  
  293.     Song.InitialTempo := 4;
  294.     Song.InitialBPM   := 80;
  295.     Song.Volume       := 255;
  296.     Song.NumChannels  := 8;
  297.  
  298.     Song.SequenceLength := 0;
  299.     FOR i := 1 TO 128 DO
  300.       IF Hdr.Sequence[i] < 128 THEN
  301.         Song.SequenceLength := i;
  302.  
  303.     Song.SequenceRepStart := Hdr.RepStart + 1;
  304.     Move(Hdr.Sequence, Song.PatternSequence^, Song.SequenceLength);
  305.     Move(Hdr.Tempos,   Song.PatternTempos^,   128);
  306.  
  307.     FOR i := 1 TO Song.SequenceLength DO
  308.       INC(Song.PatternSequence^[i]);
  309.  
  310.  
  311.     { Processing of the instruments }
  312.  
  313.     ProcessInstruments(Song, St, Hdr.NInstruments);
  314.     IF Song.Status > msOk THEN EXIT;
  315.  
  316.  
  317.     { Processing of the patterns (the partiture) }
  318.  
  319.     ProcessPatterns(Song, St, Hdr.Lengths, Hdr.NPatterns);
  320.     IF Song.Status > msOk THEN EXIT;
  321.  
  322.  
  323.     { Processing of the samples }
  324.  
  325.     ProcessSamples(Song, St, Hdr.NInstruments);
  326.     IF Song.Status > msFileTooShort THEN EXIT;
  327.   END;
  328.  
  329.  
  330.  
  331.  
  332. END.
  333.